#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <vector>
#include <nlohmann/json.hpp>
#include <unistd.h>
#include <sys/socket.h>

using std::vector;
using json = nlohmann::json;
using std::string;
using std::cin;
using std::cout;
using std::endl;

#define ARGS_CHECK(argc, n)                                        \
    {                                                              \
        if (argc != n) {                                           \
            fprintf(stderr, "ERROR: expected %d arguments.\n", n); \
            exit(1);                                               \
        }                                                          \
    }
    
#define ERROR_CHECK(retval, val, msg) \
    {                                 \
        if (retval == val) {          \
            perror(msg);              \
            exit(1);                  \
        }                             \
    }

class Client {
public:
    Client();
    ~Client();
    void start(const char *ip, const char *port);
    int sendTrain(json &ptrain);
    int recvTrain(json &ptrain);
    void clientCmd();

private:
    int _sockfd;
    int recvn(int fd, string &s_recv, int length);
    int clientTcpInit(const char *ip, const char *port);
};

// cli_msg and ser_msg classes and related functions
// ...
#ifndef __CLI_MSG__
#define __CLI_MSG__
class cli_msg
{
public:
  int msgid;
  string data; 
};
void cli_to_json(json &j, const cli_msg &m)
{
j= json{
{"msgid", m.msgid},
{"data", m.data} };
}

void cli_from_json(const json &j, cli_msg &m)
{

j.at("msgid").get_to(m.msgid);
j.at("data").get_to(m.data);
}
#endif

#ifndef __SER_MSG__
#define __SER_MSG__
class ser_msg
{
public:
  int msgid;
  vector<string> data;
};
void ser_to_json(json &j, const ser_msg &m)
{
j= json{ 
{"msgid",m.msgid},
{"data", m.data} };
}

void ser_from_json(const json &j, ser_msg &m)
{

j.at("msgid").get_to(m.msgid);
j.at("data").get_to(m.data);
}
#endif
//int g_sockfd;